#!/usr/bin/env python

import sys
import gobject
import run
from subprocess import call

Run = run.Run()
import io
IO = io.IO()

try:
 	import pygtk
  	pygtk.require("2.0")
except:
  	pass
try:
	import gtk
  	import gtk.glade
except:
	sys.exit(1)
    
    
class TuringSimulator:

    def __init__(self):
    	call(["mkdir", "-p", "/home/turing"])
        builder = gtk.Builder()
        builder.add_from_file("src/pytsgui.xml") 
        
        self.window = builder.get_object("MainWindow")
        self.codeTree = builder.get_object("codeTree")
        self.tapeTree = builder.get_object("tapeTree")
        self.startSide = builder.get_object("comboStartSide")
        self.statusbar = builder.get_object("statusbar")
        self.resultTree = builder.get_object("resultTree")

        builder.connect_signals(self)       
        
        #Disse tre linier skal bruges til at lave et tooltip!
        self.btnAddLine = builder.get_object("btnAddLine")
        self.tooltips = gtk.Tooltips()
        self.tooltips.set_tip(self.btnAddLine, "Add new line to program")

        self.startSideStore = gtk.ListStore(gobject.TYPE_STRING)
        
        cell = gtk.CellRendererText()
        self.startSide.pack_start(cell, True)
        self.startSide.add_attribute(cell, 'text',0)
        self.startSide.set_model(self.startSideStore)
        self.startSideStore.append (["Left"])
        self.startSideStore.append (["Right"])
        self.startSide.set_active(1)
        
        ########################################### codeTree ######################################################
        self.treeList = gtk.ListStore(gobject.TYPE_PYOBJECT, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
        #Attache the model to the treeView
        self.codeTree.set_model(self.treeList)
        
        self.iState = 1
        self.iTape = 2
        self.iReplace = 3
        self.iMove = 4
        self.iGoto = 5
        self.sState = "State"
        self.sTape = "Symbol"
        self.sReplace = "Replace with"
        self.sMove = "Move"
        self.sGoto = "Go to state"
        self.AddListColumn(self.sState, self.iState)
        self.AddListColumn(self.sTape, self.iTape)
        self.AddListColumn(self.sReplace, self.iReplace)
        self.AddListColumn(self.sMove, self.iMove)
        self.AddListColumn(self.sGoto, self.iGoto)
        self.codeTreeCounter = 1
        self.treeList.append([self.codeTreeCounter,"start","*","*","L",""])


        ########################################### SLUT ###########################################
    
        ############################################# tapeTree ###########################################
         
        self.TapeLength = 15
         
        columns = [gobject.TYPE_STRING]*self.TapeLength
        self.tapeList = gtk.ListStore(*columns)
        self.tapeTree.set_model(self.tapeList)
        

        for i in range(0,self.TapeLength):
            txtTapeRenderer = gtk.CellRendererText()
            txtTapeRenderer.set_property("editable", True)
            column = gtk.TreeViewColumn(str(i), txtTapeRenderer, text=i)
            column.set_resizable(True)
            txtTapeRenderer.connect("edited", self.TapeCellEdited, (self.tapeTree.get_model(), i))
            #column.set_sort_column_id(columnId)
            self.tapeTree.append_column(column)
            column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
            column.set_fixed_width(50)
            txtTapeRenderer.set_property('xalign', 0.5)
            
        
        self.tapeList.append(["*"," "," "," "," "," "," "," "," "," "," "," "," "," ","*"])
        ############################################ slut ###############################################
    

        ########################################### resultTree ############################################
        
                
        self.RTapeLength = self.TapeLength
         
        columns = [gobject.TYPE_STRING]*self.RTapeLength
        self.resultList = gtk.ListStore(*columns)
        self.resultTree.set_model(self.resultList)
        

        for i in range(0,self.RTapeLength):
            txtRTapeRenderer = gtk.CellRendererText()
            txtRTapeRenderer.set_property("editable", False)
            column = gtk.TreeViewColumn(str(i), txtRTapeRenderer, text=i)
            column.set_resizable(True)
            self.resultTree.append_column(column)
            column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
            column.set_fixed_width(50)
            txtRTapeRenderer.set_property('xalign', 0.5)
            
        
        self.resultList.append(["*"," "," "," "," "," "," "," "," "," "," "," "," "," ","*"])
        
        
        ##############################################################################################
    def on_codeTree_cursor_changed(self,path):
        
        
        self.codeTree.get_selection().connect('changed',self.CellEdited, "test")
        #self.codeTree.get_selection().connect('changed',self.test)
        #maaske set cell til activatet?
        
        
        #path, focus_column = self.codeTree.get_cursor()
        #self.codeTree.get_selection().unselect_path(path)

    
    
    
    def AddListColumn(self, title, columnId):
        """This function adds a column to the list view. First it create the gtk.TreeViewColumn and then set some needed properties"""

        txtRenderer = gtk.CellRendererText()
        txtRenderer.set_property("background", "#f5f5f5")

        txtRenderer.set_property("editable", True)
        column = gtk.TreeViewColumn(title, txtRenderer, text=columnId)
        column.set_resizable(True)
        txtRenderer.connect("edited", self.CellEdited, (self.codeTree.get_model(), columnId))
        #column.set_sort_column_id(columnId)
        self.codeTree.append_column(column)
        txtRenderer.set_property('xalign', 0.5) #center text, 1.0= right


    
    def on_btnDeleteLine_clicked(self,widget,data=None):
        selection = self.codeTree.get_selection() 
        model, iter, = selection.get_selected()
        if iter:
            path = model.get_path(iter)
            model.remove(iter)

        selection.select_path(path)

        if not selection.path_is_selected(path):
            row = path[0]-1
            # test case for empty lists
            if row >= 0:
                selection.select_path((row,))
    

    def on_btnGo_clicked(self,widget, data=None):
        if self.startSide.get_active() == 0:
            self.startPosition = 1
        else:
            self.startPosition = self.TapeLength
            
        self.statusbar.push(1,"Running Program")
        
        result, stat, runMsg = Run.RunProgram(self.treeList, self.tapeList, len(self.codeTree.get_model()), self.TapeLength, self.startPosition)
        if stat != 0:
            self.error(runMsg)
        
        self.statusbar.push(1,runMsg)
        
        #fylder information i resultTape
        model = self.resultTree.get_model()
        for i in range(0, self.RTapeLength):
            model[0][i] = result[i]
        
    
    def CellEdited(self, cell, path, new_text, user_data):

        liststore, column = user_data
        liststore[path][column] = new_text
        return    
        
        
    def TapeCellEdited(self, cell, path, new_text, user_data):
        liststore, column = user_data
        liststore[path][column] = new_text
        return    

        
        
    def on_btnAddLine_clicked(self, widget, data=None):
        self.codeTreeCounter+=1
        self.treeList.append([self.codeTreeCounter,"","","","",""])
        
        
        
    def on_MainWindow_destroy(self, widget, data=None):
        gtk.main_quit()
        
    def on_toolNew_clicked(self, widget, data=None):
	self.tapeList.clear()
        self.tapeList.append(["*"," "," "," "," "," "," "," "," "," "," "," "," "," ","*"])
        self.resultList.clear()
        self.resultList.append(["*"," "," "," "," "," "," "," "," "," "," "," "," "," ","*"])
        self.codeTreeCounter = 1
	self.treeList.clear()
        self.treeList.append([self.codeTreeCounter,"start","*","*","L",""])
	self.Ofilename = "/home/turing"	

        
    def on_toolExit_clicked(self,widget,data=None):
        #tjek om der er gemt inden
        gtk.main_quit()
    
    def on_toolSave_clicked(self, widget, data=None):
	    if not hasattr(self, 'Ofilename'):
		    self.Ofilename = "/home/turing"
	    IO.SaveFile(self.treeList, self.tapeList, self.Ofilename)
        
    def on_toolSaveAs_clicked(self, widget, data=None):
        	
        chooser = gtk.FileChooserDialog(title='Save file as',action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK))
        filter = gtk.FileFilter()
        filter.set_name("Turing machine code")
        filter.add_pattern("*.tmc")
        chooser.add_filter(filter)
        response = chooser.run()
        if response == gtk.RESPONSE_OK:
            self.Ofilename = chooser.get_filename()
            IO.SaveFile(self.treeList, self.tapeList, self.Ofilename)

        elif response == gtk.RESPONSE_CANCEL:
            print 'Closed, no files selected'
        chooser.destroy()
        

    def on_toolOpen_clicked(self, widget, data=None):
        	
        chooser = gtk.FileChooserDialog(title='Open File',action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
        filter = gtk.FileFilter()
        filter.set_name("Turing machine code")
        filter.add_pattern("*.tmc")
        chooser.add_filter(filter)
        response = chooser.run()
        if response == gtk.RESPONSE_OK:
            self.ifilename = chooser.get_filename()
            LoadCode, LoadTape = IO.OpenFile(self.ifilename)
        elif response == gtk.RESPONSE_CANCEL:
            print 'Closed, no files selected'
        chooser.destroy()
        
        #add loaded tape to the tape
        model = self.tapeTree.get_model()
        for i in range(0, self.TapeLength):
            model[0][i] = LoadTape[i]
            
        #add the loaded code to the codeTree
        for i in range((len(LoadCode)-1)):                                                                  #add lines
            self.treeList.append([self.codeTreeCounter,"","","","",""])
        cmodel = self.codeTree.get_model()
        for i in range(len(LoadCode)):                                                                        #number of lines
            for e in range(len(LoadCode[0])):
                cmodel[i][e] = LoadCode[i][e]




    def on_toolAbout_clicked(self, widget, data=None):
        
        authors = ["Jim Trebbien <jim.trebbien@gmail.com>"]
        

        
        dialog = gtk.AboutDialog()
        dialog.set_transient_for(self.window)
        dialog.set_destroy_with_parent(True)
        dialog.set_name("PyTS")
        #major.minor.revision
        dialog.set_version("0.5.1a")
        dialog.set_copyright("\302\251 Copyright 2008 Jim Trebbien")
        dialog.set_website("http://pyts.googlecode.com")
        dialog.set_authors(authors)
        dialog.set_logo_icon_name(gtk.STOCK_EXECUTE)
        dialog.set_comments("Turing machine simulator written in pygtk")
   	   ## Close dialog on user response
        dialog.connect ("response", lambda d, r: d.destroy())
        dialog.show()

    def error(self, error_string):
        error_dlg = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, message_format=error_string, buttons=gtk.BUTTONS_OK)
        error_dlg.run()
        error_dlg.destroy()


if __name__ == "__main__":
    TS = TuringSimulator()
    TS.window.show()
    gtk.main()
